package com.digua.base.base

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONArray
import com.blankj.utilcode.util.ViewUtils
import com.digua.base.util.CollUtil
import com.digua.base.util.ViewUtil
import java.lang.reflect.ParameterizedType

abstract class RecyclerViewAdapter<UI : ViewBinding, D> : RecyclerView.Adapter<RecyclerView.ViewHolder> {
    protected var context: Context
    val datas = ArrayList<D>()

    protected var onItemClickListener: OnItemClickListener<D>? = null
        protected get() = field

    constructor(context: Context, datas: ArrayList<D>? = null) {
        this.context = context
        setDatas(datas)
    }

    open fun setDatas(datas: ArrayList<D>?) {
        var list: ArrayList<D> = ArrayList()
        if (CollUtil.isNotBlank(datas)) {
            val json: String = JSON.toJSONString(datas)
            list = JSONArray.parseArray(json, datas?.get(0)!!::class.java) as ArrayList<D>
        }
        this.datas.clear()
        addDatas(list)
    }

    fun addDatas(datas: ArrayList<D>) {
        if (CollUtil.isNotBlank(datas)) {
            this.datas.addAll(datas)
            notifyItemRangeInserted(this.datas.size - 1, datas.size)
        } else {
            notifyDataSetChanged()
        }
    }

    fun addData(data: D?) {
        ViewUtils.runOnUiThread {
            data?.let {
                this.datas.add(it)
                notifyItemInserted(datas.size - 1)
            }
        }
    }

    fun getItem(position: Int) = if (position >= 0 && position < datas.size) datas[position] else null

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val vh = holder as ViewHolder<*>
        val data: D? = datas[position]
        bindHolder(vh.ui as UI, position, data)
        onItemClickListener?.let { listener ->
            vh.ui.root.tag = position
            if (listener.hasReClick) {
                ViewUtil.onClickNoReClick(vh.ui.root) {
                    val index = it.tag as Int
                    listener.onItemClick(getItem(index), index)
                }
            } else {
                ViewUtil.onClick(vh.ui.root) {
                    val index = it.tag as Int
                    listener.onItemClick(getItem(index), index)
                }
            }
        }
    }

    abstract fun bindHolder(ui: UI, position: Int, data: D?)

    override fun getItemCount() = datas.size as Int

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val type = javaClass.genericSuperclass as ParameterizedType
        val cls = type.actualTypeArguments[0] as Class<*>
        val inflate = cls.getDeclaredMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.javaPrimitiveType)
        val ui: UI = inflate.invoke(null, LayoutInflater.from(context), parent, false) as UI
        return ViewHolder(ui)
    }

    /**
     * 不重写此方法时，item复用会错乱
     *
     * @param position
     * @return
     */
    override fun getItemViewType(position: Int) = position

    //注意：此处不能写成 super.getItemId(position); 否则会偶发性的出现Item重复
    override fun getItemId(position: Int) = position.toLong()

    abstract class OnItemClickListener<D>(hasReClick: Boolean) {
        var hasReClick = hasReClick
        abstract fun onItemClick(data: D?, position: Int)
    }

    open class ViewHolder<UI : ViewBinding>(ui: UI) : RecyclerView.ViewHolder(ui.root) {
        var ui: UI = ui
    }

    protected fun getFragmentManager(): FragmentManager? {
        if (context is FragmentActivity) {
            return (context as FragmentActivity).supportFragmentManager
        } else if (context is Activity<*>) {
            return (context as Activity<*>).supportFragmentManager
        }
        return null
    }
}